#!/usr/bin/env python3
"""
本地测试运行脚本
无需Docker，使用Mock和内存数据库进行测试
"""

import os
import sys
import subprocess
import sqlite3
from pathlib import Path

def setup_local_test_environment():
    """设置本地测试环境"""
    print("🚀 设置本地测试环境...")
    
    # 创建必要的目录
    directories = [
        "tests/data/raw",
        "tests/data/processed", 
        "tests/data/expected",
        "tests/data/mock_apis",
        "tests/logs",
        "tests/reports"
    ]
    
    for directory in directories:
        os.makedirs(directory, exist_ok=True)
        print(f"✅ 创建目录: {directory}")
    
    # 创建SQLite测试数据库
    create_test_database()
    
    print("✅ 本地测试环境设置完成!")

def create_test_database():
    """创建SQLite测试数据库"""
    print("📊 创建SQLite测试数据库...")
    
    db_path = "tests/data/test_vulnerability_kg.db"
    
    # 删除旧数据库
    if os.path.exists(db_path):
        os.remove(db_path)
    
    # 创建新数据库和表
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    
    # 漏洞表
    cursor.execute('''
        CREATE TABLE vulnerabilities (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            cve_id TEXT UNIQUE NOT NULL,
            title TEXT,
            description TEXT,
            severity TEXT,
            cvss_score REAL,
            published_date TEXT,
            modified_date TEXT,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    ''')
    
    # 产品表
    cursor.execute('''
        CREATE TABLE products (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            vendor TEXT,
            version TEXT,
            cpe_id TEXT,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    ''')
    
    # 关系表
    cursor.execute('''
        CREATE TABLE vulnerability_product_relations (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            vulnerability_id INTEGER,
            product_id INTEGER,
            relation_type TEXT DEFAULT 'AFFECTS',
            confidence REAL DEFAULT 1.0,
            FOREIGN KEY (vulnerability_id) REFERENCES vulnerabilities (id),
            FOREIGN KEY (product_id) REFERENCES products (id)
        )
    ''')
    
    # 插入测试数据
    test_vulnerabilities = [
        ('CVE-2023-TEST-001', 'Test Vulnerability 1', 'Test description 1', 'HIGH', 8.5, '2023-01-01', '2023-01-02'),
        ('CVE-2023-TEST-002', 'Test Vulnerability 2', 'Test description 2', 'MEDIUM', 6.8, '2023-01-03', '2023-01-04'),
        ('CVE-2023-TEST-003', 'Test Vulnerability 3', 'Test description 3', 'CRITICAL', 9.2, '2023-01-05', '2023-01-06'),
    ]
    
    cursor.executemany('''
        INSERT INTO vulnerabilities (cve_id, title, description, severity, cvss_score, published_date, modified_date)
        VALUES (?, ?, ?, ?, ?, ?, ?)
    ''', test_vulnerabilities)
    
    test_products = [
        ('Apache HTTP Server', 'Apache', '2.4.50', 'cpe:2.3:a:apache:http_server:2.4.50'),
        ('Nginx Web Server', 'Nginx', '1.20.0', 'cpe:2.3:a:nginx:nginx:1.20.0'),
        ('MySQL Database', 'Oracle', '8.0.25', 'cpe:2.3:a:oracle:mysql:8.0.25'),
    ]
    
    cursor.executemany('''
        INSERT INTO products (name, vendor, version, cpe_id)
        VALUES (?, ?, ?, ?)
    ''', test_products)
    
    # 创建关系
    cursor.execute('''
        INSERT INTO vulnerability_product_relations (vulnerability_id, product_id, relation_type, confidence)
        VALUES (1, 1, 'AFFECTS', 0.95)
    ''')
    
    cursor.execute('''
        INSERT INTO vulnerability_product_relations (vulnerability_id, product_id, relation_type, confidence)
        VALUES (2, 2, 'AFFECTS', 0.88)
    ''')
    
    conn.commit()
    conn.close()
    
    print(f"✅ SQLite数据库创建完成: {db_path}")

def generate_test_data():
    """生成测试数据"""
    print("📝 生成测试数据...")
    
    try:
        # 运行测试数据生成脚本
        result = subprocess.run([
            sys.executable, "tests/data/generate_test_data.py"
        ], capture_output=True, text=True, timeout=60)
        
        if result.returncode == 0:
            print("✅ 测试数据生成完成")
        else:
            print(f"⚠️ 测试数据生成警告: {result.stderr}")
            
    except subprocess.TimeoutExpired:
        print("⚠️ 测试数据生成超时，使用默认数据")
    except Exception as e:
        print(f"⚠️ 测试数据生成失败: {e}")

def install_test_dependencies():
    """安装测试依赖"""
    print("📦 检查并安装测试依赖...")
    
    try:
        # 检查pytest是否已安装
        subprocess.run([sys.executable, "-c", "import pytest"], check=True, capture_output=True)
        print("✅ pytest已安装")
    except subprocess.CalledProcessError:
        print("📦 安装pytest...")
        subprocess.run([sys.executable, "-m", "pip", "install", "pytest", "pytest-asyncio"], check=True)
    
    # 安装其他必要依赖
    essential_packages = [
        "sqlite3",  # 通常内置
        "pathlib",  # 通常内置
        "unittest.mock",  # 通常内置
    ]
    
    print("✅ 基础测试依赖检查完成")

def run_unit_tests():
    """运行单元测试"""
    print("🧪 运行单元测试...")
    
    # 设置环境变量
    os.environ['TEST_CONFIG'] = 'tests/config/local_test_settings.yaml'
    os.environ['MOCK_EXTERNAL_SERVICES'] = 'true'
    os.environ['USE_MEMORY_DB'] = 'true'
    
    try:
        # 运行pytest
        cmd = [
            sys.executable, "-m", "pytest",
            "tests/unit/",
            "-v",
            "--tb=short",
            "-x",  # 遇到第一个失败就停止
            "--timeout=60",
            f"--html=tests/reports/local_test_report.html",
            "--self-contained-html"
        ]
        
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        print(f"📊 测试结果:")
        print(result.stdout)
        
        if result.stderr:
            print(f"⚠️ 警告信息:")
            print(result.stderr)
        
        if result.returncode == 0:
            print("✅ 所有单元测试通过!")
        else:
            print(f"❌ 有 {result.returncode} 个测试失败")
            
        return result.returncode == 0
        
    except Exception as e:
        print(f"❌ 运行测试时出错: {e}")
        return False

def create_simple_unit_test():
    """创建一个简单的单元测试用于验证环境"""
    test_content = '''
import pytest
import sqlite3
import os
from pathlib import Path

def test_environment_setup():
    """测试环境是否正确设置"""
    # 检查数据库文件是否存在
    db_path = "tests/data/test_vulnerability_kg.db"
    assert os.path.exists(db_path), f"数据库文件不存在: {db_path}"
    
    # 检查数据库连接
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    
    # 检查表是否存在
    cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
    tables = [row[0] for row in cursor.fetchall()]
    
    expected_tables = ['vulnerabilities', 'products', 'vulnerability_product_relations']
    for table in expected_tables:
        assert table in tables, f"数据库表不存在: {table}"
    
    # 检查测试数据
    cursor.execute("SELECT COUNT(*) FROM vulnerabilities")
    vuln_count = cursor.fetchone()[0]
    assert vuln_count > 0, "漏洞表中没有测试数据"
    
    cursor.execute("SELECT COUNT(*) FROM products")
    prod_count = cursor.fetchone()[0]
    assert prod_count > 0, "产品表中没有测试数据"
    
    conn.close()

def test_mock_functionality():
    """测试Mock功能"""
    # 简单的Mock测试
    from unittest.mock import Mock
    
    mock_crawler = Mock()
    mock_crawler.extract_cve_id.return_value = "CVE-2023-12345"
    
    result = mock_crawler.extract_cve_id("test content")
    assert result == "CVE-2023-12345"

def test_file_operations():
    """测试文件操作"""
    test_file = Path("tests/data/test_file.txt")
    
    # 写入测试数据
    test_file.write_text("测试数据", encoding='utf-8')
    
    # 读取测试数据
    content = test_file.read_text(encoding='utf-8')
    assert content == "测试数据"
    
    # 清理
    test_file.unlink()

def test_basic_imports():
    """测试基础模块导入"""
    import json
    import sqlite3
    import pathlib
    import unittest.mock
    
    # 测试JSON操作
    test_data = {"test": "data"}
    json_str = json.dumps(test_data)
    parsed_data = json.loads(json_str)
    assert parsed_data == test_data
'''
    
    # 创建测试文件
    test_file = Path("tests/unit/test_environment.py")
    test_file.write_text(test_content, encoding='utf-8')
    print(f"✅ 创建基础测试文件: {test_file}")

def main():
    """主函数"""
    print("🚀 启动本地测试环境...")
    
    try:
        # 1. 设置环境
        setup_local_test_environment()
        
        # 2. 安装依赖
        install_test_dependencies()
        
        # 3. 生成测试数据
        generate_test_data()
        
        # 4. 创建基础测试
        create_simple_unit_test()
        
        # 5. 运行测试
        success = run_unit_tests()
        
        if success:
            print("\n🎉 恭喜! 本地测试环境设置成功并运行通过!")
            print("\n📊 查看测试报告:")
            print("   - HTML报告: tests/reports/local_test_report.html")
            print("   - 数据库: tests/data/test_vulnerability_kg.db")
            print("   - 日志: tests/logs/local_test.log")
        else:
            print("\n⚠️ 测试未完全通过，但环境已设置。请检查错误信息。")
            
        print("\n🔧 下一步:")
        print("   1. 检查测试报告")
        print("   2. 根据需要修改测试配置")
        print("   3. 运行更多测试: python -m pytest tests/unit/ -v")
        
    except KeyboardInterrupt:
        print("\n⏹️ 用户中断测试")
    except Exception as e:
        print(f"\n❌ 设置过程中出错: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main() 